package com.example.controller;
import com.example.model.pojo.User;
import com.example.model.pojo.Result;
import com.example.model.service.UserService;
import com.example.utils.JwtUtil;
import com.example.utils.Md5Util;
import com.example.utils.ThreadLocalUtil;
import jakarta.validation.constraints.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@Validated
public class UserController {
    @Autowired
    private UserService userService;
    @RequestMapping("/findById")
    public User findById(Integer id){
        //写了前端能用的接口controller要调用真的接口服务service
        return userService.findById(id);
    }
    @RequestMapping("/findByusername")
    public User findByusername(String username){
        return userService.findByUserName(username);
    }
    @PostMapping("/register")
    public Result register(@Pattern(regexp = "^\\S{5,16}$") String username,@Pattern(regexp = "^\\S{5,16}$") String password){
        //新手做法
        /*if(username!=null && username.length()>=5 && username.length()<=16 &&
         password!=null && password.length()>=5 && password.length()<=16){*/
        //查询用户
        User u = userService.findByUserName(username);
        if(u==null){
            //没有用户
            //注册
            //还有参数校验，参数校验在接口搞虽然说我也不知道写在别处会怎么样
            userService.register(username,password);
            return Result.success();
        }else{
            return Result.error("已有用户名");
        }
        //如果不想写到累死，使用spring Validation 对注册接口的参数进行合法性校验
        //引入Spring Validation起步依赖
        //在参数前面添加@Pattern注解
        //在Controller类上添加@Validated注解
        //虽然说这种长度不长度的反正是前端搞，但是还是要写个接受异常类
    }
    @PostMapping("/login")

    public Result<String> login(@Pattern(regexp = "^\\S{5,16}$") String username,String password){
        //根据用户名查询User
        User loginUser = userService.findByUserName(username);
        //判断是否查询到
        if(loginUser==null){
            return Result.error("用户名错误");
        }
        //判断密码是否正确 loginUser对象中的password是密文
        if(Md5Util.getMD5String(password).equals(loginUser.getPassword())){
            //
            Map<String,Object> claims = new HashMap<>();
            claims.put("id",loginUser.getId());
            claims.put("username",loginUser.getUsername());
            String token = JwtUtil.genToken(claims);
            return Result.success(token);
        }
        return Result.error("密码错误");
    }
    //那么如何完成登录后才可以访问别的接口呢
    //jwt定义了简洁的、自包含的格式，用于通信双方以json数据格式安全的传输信息
    //一坨base64码，第一托是头，记载令牌类型，签名算法，第二托是有效信息，最后一坨是加密码，确保安全，无法篡改
    //不用自己会写，全是用工具

    //有点离谱的获取token然后得到用户数据，反正实战不是这么做
    @GetMapping("/userinfo")
    public Result<User> userInfo( /*@RequestHeader(name="Authorization") String token*/ ){
        //Map<String,Object> map = JwtUtil.parseToken(token);
        //String username = (String)map.get("username");
        Map<String,Object>map = ThreadLocalUtil.get();
        String username = (String) map.get("username");
        User user = userService.findByUserName(username);
        return Result.success(user);
    }
    //ThreadLocal提供线程局部变量，保障线程安全,在拦截器解析token
    //@Validated让实体类校验生效
    @PutMapping("/update")
    public Result update(@RequestBody @Validated User user){
        userService.update(user);
        return Result.success();
    }
    @PatchMapping("/updateAvatar")
    public Result updateAvatar(@RequestParam String avatarUrl){
        userService.updateAvatar(avatarUrl);
        return Result.success();
    }
    //因为改密码的话呢又不能重新登录一次又要看用户输入的密码对不对，所以又在这里获取一下token
    //然后肯定是前端传入个map进来这样密码新密码什么的
    //改密码后老令牌还是有效的,所以说要用radis技术对比令牌
    @PatchMapping("/updatePwd")
    public Result updetePwd(@RequestBody Map<String, String> params,@RequestHeader("Authorization") String token){
        //1.校验参数。
        String oldPwd = params.get("old_pwd");
        String newPwd = params.get("new_pwd");
        String rePwd = params.get("re_pwd");
        if (!StringUtils.hasLength(oldPwd) || !StringUtils.hasLength(newPwd) || !StringUtils.hasLength(rePwd)) {
            return Result.error("缺少必要的参数");
        }
        //原密码是否正确
        //调用userService根据用户名拿到原密码,再和old_pwd比对
        Map<String,Object> map = ThreadLocalUtil.get();
        String username = (String) map.get("username");
        User loginUser = userService.findByUserName(username);
        if(!loginUser.getPassword().equals(Md5Util.getMD5String(oldPwd))){
            return Result.error("原密码填写不正确");
        }
        //newPwd和rePwd是否一样
        if (!rePwd.equals(newPwd)){
            return Result.error("两次填写的新密码不一样");
        }
        //2.调用service完成密码更新
        userService.updatePwd(newPwd);
        //删除redis中对应的token
        //ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        //operations.getOperations().delete(token);
        return Result.success();
    }
}
